package pimmodel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observer;

import pimgui.PimGui;

/**
 * 
 * Klasse Kontakt:<br>
 * Die Klasse Kontakt beinhaltet alle wesentlichen Kontaktdaten und <br>
 * die entsprechenden Verwaltungsmethoden.
 * 
 * @authors (Torsten Mansfeld, Thomas Schoenfeld)
 * @version (20120902_01)
 * 
 */
public class Kontakt extends PimDaten implements IKontakt {

	// Serialisierungs-UID
	private static	final	long				serialVersionUID	= 1L;
	
	
	
	// Meldungskonstanten
	private	static	final	String				VORNAME				= "Der uebergebene Vorname ist kein gueltiger String.";
	private	static	final	String				EMAIL				= "Die uebergebene E-Mail-Adresse ist kein gueltiger String.";
	private static	final	String				IKONTAKT			= "Das uebergebene Objekt ist nicht vom Typ Kontakt.";
	private	static	final	String				ITELEFONNR			= "Das uebergebene Objekt ist nicht vom Typ ITelefonnr.";
	private	static	final	String				IADRESSE			= "Das uebergebene Objekt ist nicht vom Typ IADRESSE.";
	private	static	final	String				TELEFONNR			= "Das uebergebene Objekt ist null.";
	
		
	
	// Instanzvariablen
	private					String				vorname;
	private					String				email;
	private					IAdresse			adresse;
	private					List<ITelefonnr>	telefonnummern;
	private					Observer			observer;
	
	
	
	// Konstrunktoren
	
	/**
	 * Standardkonstruktor der Klasse Kontakt.
	 */
	public Kontakt() {
		
		this( "Initial", "", "", "", "", "", "", "", "", "", null );
		telefonnummern	= new ArrayList<ITelefonnr>();
		
	}
	
	/**
	 * Konstruktor der Klasse Kontakt:<br>
	 * Die Angabe des Namens ist verpflichtend. <br>
	 * Es muss mindestens eine Kontaktmoeglichkeit angegeben werden.
	 * 
	 * @param	name		der Name des Kontakts
	 * @param	vorname		der Vorname des Kontakts (optional)
	 * @param	strasse		die Strasse als Teil der Anschrift (optional)
	 * @param	hausnummer	die Hausnummer als Teil der Anschrift (optional)
	 * @param	plz			die Postleitzahl als Teil der Anschrift (optional)
	 * @param	ort			der Wohnort / Sitz als Teil der Anschrift (optional)
	 * @param	land		das Land als Teil der Anschrift (optional)
	 * @param	email		die E-Mail-Adresse (optional)
	 * @param	teltyp		der Telefontyp: Festnetz - Mobil - Fax (optional)
	 * @param	telnr		die Telefonnummer (optional)
	 * @param	observer	Observer
	 * 
	 * @throws				IllegalArgumentException falls uebergebene Parameter ungueltig sind
	 */
	public Kontakt(	final String name, final String vorname, final String strasse, final String hausnummer, final String plz,
					final String ort, final String land, final String email, final String teltyp, final String telnr,
					final Observer observer ) {
		
		super( name );
		
		if ( vorname instanceof String )
			setVorname( vorname );
		
		if ( email instanceof String )
			setEmail( email );
				
		adresse = new Adresse();
		
		if ( ort instanceof String && !( ort.trim().isEmpty() ) )
		{
			setAdresse( new Adresse( strasse, hausnummer, plz, ort, land ) );
		}
		
		telefonnummern	= new ArrayList<ITelefonnr>();
		
		if ( teltyp instanceof String && !( teltyp.trim().isEmpty() ) &&
			 telnr  instanceof String && !(  telnr.trim().isEmpty() )  )
		{
			
			addTelefonnr( new Telefonnr( teltyp, telnr ) );
		}		 			
		
		this.observer = observer;
		
		if ( this.observer != null )
			this.addObserver( this.observer );
		
	}	
	
	/**
	 * Kopierkonstruktor der Klasse Kontakt.
	 * 
	 * @param	kontakt		der zu kopierende Kontakt
	 * 
	 * throws				IllegalArgumentException falls das uebergebene Objekt nicht vom Typ IKontakt ist.
	 */
	public Kontakt( final IKontakt kontakt ) {
				
		if ( ! ( kontakt instanceof IKontakt ) )
			throw new IllegalArgumentException( IKONTAKT );

		telefonnummern	= new ArrayList<ITelefonnr>();
		
		setName( kontakt.getName() );
		setVorname( kontakt.getVorname() );
		setEmail( kontakt.getEmail() );
		setAdresse( new Adresse( 
					kontakt.getStrasse(),
					kontakt.getHausnummer(),
					kontakt.getPlz(),
					kontakt.getOrt(),
					kontakt.getLand() ) );
		setTelefonnummern( kontakt.getTelefonnummern() );		
		
		this.observer = ( ( Kontakt )kontakt ).observer;
		
		if ( observer != null )
			this.addObserver( this.observer );
		
	}		
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#addTelefonnr(pimmodel.ITelefonnr)
	 */
	@Override
	public void addTelefonnr( final ITelefonnr neuTel ) {
		
		if ( !( neuTel instanceof ITelefonnr ) )
			throw new IllegalArgumentException( ITELEFONNR );
		
		this.telefonnummern.add( neuTel );
		
		telefonnummernSortieren();
		
		this.notifyObservers( this.telefonnummern );
		
	}
	
	
	
	// Getter und Setter Methoden

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getName()
	 */
	@Override
	public String getName() {
		
		return super.getName();
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setName(java.lang.String)
	 */
	@Override
	public void setName( final String name ) {		
		
		super.setName( name );
		
		this.notifyObservers( this.getName() );
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getVorname()
	 */
	@Override
	public String getVorname() {
		
		return vorname;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setVorname(java.lang.String)
	 */
	@Override
	public void setVorname( final String vorname ) {
		
		if ( !( vorname instanceof String ) )
			throw new IllegalArgumentException( VORNAME );
		
		this.vorname = vorname.trim();
		
		this.notifyObservers( this.getVorname() );
		
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getEmail()
	 */	
	@Override
	public String getEmail() {
		
		return email;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setEmail(java.lang.String)
	 */	
	@Override
	public void setEmail( final String email ) {
		
		if ( !( email instanceof String ) )
			throw new IllegalArgumentException( EMAIL );
		
		this.email = email.trim();
		
		this.notifyObservers( this.getEmail() );
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getStrasse()
	 */	
	@Override
	public String getStrasse() {
		
		return adresse.getStrasse();
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setStrasse(java.lang.String)
	 */		
	@Override
	public void setStrasse( final String strasse ) {
		
		this.adresse.setStrasse( strasse );
		
		this.notifyObservers( this.getStrasse() );
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getHausnummer()
	 */		
	@Override
	public String getHausnummer() {
		
		return adresse.getHausnummer();
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setHausnummer(int)
	 */			
	@Override
	public void setHausnummer( final String hausnummer ) {
		
		this.adresse.setHausnummer( hausnummer );
		
		this.notifyObservers( this.getHausnummer() );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getPlz()
	 */	
	@Override
	public String getPlz() {
		
		return adresse.getPlz();
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setPlz(java.lang.String)
	 */				
	@Override
	public void setPlz( final String plz ) {
		
		this.adresse.setPlz( plz );
		
		this.notifyObservers( this.getPlz() );
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getOrt()
	 */		
	@Override
	public String getOrt() {
		
		return adresse.getOrt();
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setOrt(java.lang.String)
	 */					
	@Override
	public void setOrt( final String ort ) {
		
		this.adresse.setOrt( ort );
		
		this.notifyObservers( this.getOrt() );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getLand()
	 */			
	@Override
	public String getLand() {
		
		return adresse.getLand();
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setLand(java.lang.String)
	 */					
	@Override
	public void setLand( final String land ) {
		
		this.adresse.setLand( land );
		
		this.notifyObservers( this.getLand() );
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getAdresse()
	 */				
	@Override
	public IAdresse getAdresse() {
		
		return new Adresse ( adresse );
		
	}
	

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setAdresse(pimmodel.IAdresse)
	 */							
	@Override
	public void setAdresse( final IAdresse adresse ) {
		
		if ( !( adresse instanceof IAdresse ) )
			throw new IllegalArgumentException( IADRESSE );
		
		this.adresse = new Adresse( adresse );
		
		this.notifyObservers( this.getAdresse() );
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#getTelefonnummern()
	 */				
	@Override
	public List<ITelefonnr> getTelefonnummern() {
		
		List<ITelefonnr> telefonnr = new ArrayList<ITelefonnr>();
		
		telefonnummernSortieren();
		
		for ( ITelefonnr telnr : this.telefonnummern ) {
			
			telefonnr.add( telnr );
			
		}
		
		return telefonnr;
		
	}
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setTelefonnummern(java.util.List)
	 */						
	@Override
	public void setTelefonnummern( final List<ITelefonnr> telefonnr ) {
		
		if ( telefonnr == null )
			throw new NullPointerException( TELEFONNR );
		
		// tiefe Kopie
		for ( ITelefonnr telnr : telefonnr ) {
		
			this.telefonnummern.add( new Telefonnr ( telnr ) );
			
		}
		
		telefonnummernSortieren();
		
		this.notifyObservers( this.getTelefonnummern() );
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#setTelefonnummern(java.util.List)
	 */						
	@Override
	public void setTelefonnummernneu( final List<ITelefonnr> telefonnr ) {
		
		if ( telefonnr == null )
			throw new NullPointerException( TELEFONNR );
		
		
		this.telefonnummern = telefonnr;
		
		
		this.notifyObservers( this.getTelefonnummern() );
		
	}

	
	
	// sonstige Methoden
	
	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#toString()
	 */
	@Override
	public String toString() {
		
		String ausgabe=PimGui.getResourceBundle().getString("Kon_n")+"     "  + getName() +PimGui.getResourceBundle().getString("Kon_1")  +
				PimGui.getResourceBundle().getString("Kon_v")+"                  "  + getVorname() + PimGui.getResourceBundle().getString("Kon_1") +
					  PimGui.getResourceBundle().getString("Kon_s")+"       "  + getStrasse() + PimGui.getResourceBundle().getString("Kon_1") +
					  PimGui.getResourceBundle().getString("Kon_h")+"           " + getHausnummer() + PimGui.getResourceBundle().getString("Kon_1") +
					   PimGui.getResourceBundle().getString("Kon_p")+"                "  + getPlz() + PimGui.getResourceBundle().getString("Kon_1") +
					  PimGui.getResourceBundle().getString("Kon_o") +"            "+ getOrt() + PimGui.getResourceBundle().getString("Kon_1") +
					   PimGui.getResourceBundle().getString("Kon_l")+"                  "+ getLand() + PimGui.getResourceBundle().getString("Kon_1") +
					   PimGui.getResourceBundle().getString("Kon_e")+"                             " + getEmail() + PimGui.getResourceBundle().getString("Kon_1") +
					    PimGui.getResourceBundle().getString("Kon_v_t");
		
		for (int i=0;i<getTelefonnummern().size();i++){
			  ausgabe+=getTelefonnummern().get(i).toString()+ PimGui.getResourceBundle().getString("Kon_1");
		}
					  
		return ausgabe;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#hashCode()
	 */
	@Override
	public int hashCode() {
		
		final int prime = 31;
		
		int result = super.hashCode();
		
		result = prime * result + ( ( adresse == null ) ? 0 : adresse.hashCode() );
		result = prime * result + ( ( email == null ) ? 0 : email.hashCode() );
		result = prime * result	+ ( ( telefonnummern == null ) ? 0 : telefonnummern.hashCode() );
		result = prime * result + ( ( vorname == null ) ? 0 : vorname.hashCode() );
		
		return result;
		
	}

	/* (non-Javadoc)
	 * @see pimmodel.IKontakt#equals(java.lang.Object)
	 */
	@Override
	public boolean equals( final Object obj) {
		
		if ( this == obj )
			return true;
		if ( !super.equals( obj ) )
			return false;
		if ( getClass() != obj.getClass() )
			return false;
		
		IKontakt other = ( IKontakt ) obj;

		if ( getName() == null ) {
			if ( other.getName() != null )
				return false;
		}
		else if ( !getName().equals( other.getName() ) )
			return false;				
		
		if ( vorname == null ) {
			if ( other.getVorname() != null )
				return false;
		}
		else if ( !vorname.equals( other.getVorname() ) )
			return false;		
		
		if (email == null) {
			if ( other.getEmail() != null )
				return false;
		}
		else if ( !email.equals( other.getEmail() ) )
			return false;
		
		if ( adresse == null ) {
			if ( other.getAdresse() != null )
				return false;
		}
		else if ( !adresse.equals( other.getAdresse() ) )
			return false;
		
		if ( telefonnummern == null ) {
			if ( other.getTelefonnummern() != null)
				return false;
		}
		else if ( !telefonnummern.equals( other.getTelefonnummern() ) )
			return false;
				
		return true;
	}

	/**
	 * compareTo		erlaubt einen lexikographischen Groessenvergleich mit einem anderen Kontakt
	 * 
	 * @param	kontakt	der zu vergleichende Kontakt
	 * 
	 * @return			-1, falls der aktuelle Kontakt lexikographisch kleiner,<br>
	 * 				 	 1, falls er groesser und<br>
	 * 				 	 0, gleich dem uebergebenen Kontakt ist
	 * 
	 * @throws			IllegalArgumentException falls das uebergebene Objekt nicht vom Typ IKontakt ist.
	 */
	@Override
	public int compareTo( final IKontakt kontakt ) {
		
		if ( ! ( kontakt instanceof IKontakt ) )
			throw new IllegalArgumentException( IKONTAKT );
		
		if ( this.getName().compareTo( kontakt.getName() ) < 0 )
			return -1;
		if ( this.getName().compareTo( kontakt.getName() ) > 0 )
			return 1;
		if ( this.vorname.compareTo( kontakt.getVorname() ) < 0 )
			return -1;
		if ( this.vorname.compareTo( kontakt.getVorname() ) > 0 )
			return 1;
		if ( this.adresse.compareTo( kontakt.getAdresse() ) < 0 )
			return -1;
		if ( this.adresse.compareTo( kontakt.getAdresse() ) > 0 )
			return 1;
		
		return 0;
		
	}
	
	
	
	// interne Sortier-Methode
	private void telefonnummernSortieren() {
		
		Collections.sort( this.telefonnummern );

	}
	
}
